const Koa = require('koa');
const config = require('./webpack.config');
const app = new Koa()
const PassThrough = require('stream').PassThrough
const mime = require('mime')
const webpack = require('webpack')
const webpackDev = require('webpack-dev-middleware')
const webpackHot = require('webpack-hot-middleware')

const port = config.devServer && config.devServer.port || 8080
const hot_client = 'webpack-hot-middleware/client?noInfo=true&reload=true'
config.mode = 'development'

if(typeof config.entry === 'string'){
    config.entry = [hot_client, config.entry]
}else if(typeof config.entry === 'object'){
    if(Array.isArray(config.entry)){
        config.entry.unshift(hot_client)
    }else{
        for(let k in config.entry){
            config.entry[k] = [hot_client, config.entry[k]]
        }
    }
}else{
    config.entry = [hot_client, './src']
}

const compiler = webpack(config)
const devMiddleware = webpackDev(compiler, {
    publicPath: config.output.publicPath,
    serverSideRender: true,
    stats: config.stats
})

const hotMiddleware = webpackHot(compiler, {
    log: false,
    heartbeat: 2000
})

app.use(async (ctx, next) => {
    await devMiddleware(ctx.req, ctx.res, next)
})

function pathMath(path){
    if(path === '/' || /^\/index(\.[^\/]+)?/.test(path)) return '/index.html'
    return path
}

app.use(async (ctx, next) => {
    if(ctx.method === 'GET'){
        const locals = ctx.res.locals
        const {outputPath} = locals.webpackStats.toJson()
        const fs = locals.fs
        const matchPath = pathMath(ctx.path)
        if(matchPath){
            try{
                const code = fs.readFileSync(outputPath+matchPath, 'utf-8')    
                const type = mime.getType(outputPath+matchPath)
                if(/javascript/.test(type)){
                    ctx.type = 'text/javascript'
                }else{
                    ctx.type = type
                }
                return ctx.body = code
            }catch(err){
            }
        }
    }
    await next()
})

app.use(async (ctx, next) => {
    let stream = new PassThrough()
    ctx.body = stream

    if(ctx.method === 'GET' && ctx.path === '/__webpack_hmr'){
        await hotMiddleware(ctx.req, {
            locals: ctx.res.locals,
            end(content){
                ctx.body = content
            },
            write() {
                stream.write.apply(stream, arguments)
            },
            writeHead: (status, headers) => {
                ctx.status = status
                ctx.set(headers)
            }
        }, next)
    }
})

app.listen(port)

